package ui.map 
{
	import com.gaiaframework.api.Gaia;
	import com.gaiaframework.api.IBitmapSprite;
	import com.gaiaframework.assets.SpriteAsset;
	import com.greensock.BlitMask;
	import com.greensock.easing.Strong;
	import com.greensock.plugins.*;
	import com.greensock.TweenLite;
	import com.greensock.TweenMax;
	import com.somerandomdude.coordy.layouts.twodee.Grid;
	import com.somerandomdude.coordy.layouts.twodee.ILayout2d;
	import flash.display.MovieClip;
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.utils.getTimer;
	import model.Model;
	import pages.Pages;
	import ui.map.Canal;
	import ui.map.MapToolTip;
	import utils.ShapeUtil;
	import utils.StringUtils;
	
	/**
	 * ...
	 * @author usual
	 */
	public class MapBackGround extends MovieClip 
	{
		private var _layout:ILayout2d;
		private var _containerMap:MovieClip;
		private var _bounds:Rectangle;
		private var _blitMask:BlitMask;
		private var t1:uint, t2:uint, y1:Number, y2:Number, x1:Number, x2:Number, xOverlap:Number, xOffset:Number, yOverlap:Number, yOffset:Number;
		
		private var _horizontalPlacementMultiple:Number = 56;
		private var _verticalPlacementMultiple:Number = 21;
		private var _gap:Number = .5;
		private var _maxZoom:Number = 2;
		private var _piXml : XML;
		private var _canal:Canal;
		private var _parisMask:ParisMask;
		private var _MarkersArray:Array;
		private var _toolTip:MapToolTip;
		private var _mapWidth:Number;
		private var _mapHeight:Number;
		public function MapBackGround() 
		{
			addEventListener(Event.ADDED_TO_STAGE, build);
			TweenPlugin.activate([ThrowPropsPlugin, RoundPropsPlugin]);
			
		}

		public function resize():void 
		{
			var sw:Number = stage.stageWidth;
			var sh:Number = stage.stageHeight;
			_bounds.x = _bounds.y = 0;
			_bounds.width = sw / _containerMap.scaleX;
			_blitMask.width = sw;
			_bounds.height =  sh / _containerMap.scaleX;
			_blitMask.height = sh;
		}
		
		public function moveToArea(area:String="map00"):void
		{
			var areaToReach:Sprite = _containerMap.getChildByName(area) as Sprite;
			var xToReach:Number = areaToReach.x;
			var yToReach:Number = areaToReach.y;
			_blitMask.removeEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
			TweenLite.to(
				_containerMap,
				4,
				{ 
					transformAroundPoint: {
						point:new Point(xToReach, yToReach),
						x:stage.stageWidth / 2, y:stage.stageHeight / 2 
					},
					ease:Strong.easeOut,
					onUpdate:function():void { /*_canal.resize();*/ _blitMask.update(); },
					onComplete:function():void { 
						_blitMask.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler); 
						_blitMask.disableBitmapMode();
					}
				}
			);
			
		}
		
		
		public function addObjectToArea(obj:*, pos:String, xPos:Number = 0, yPos:Number = 0):void
		{
			var areaToReach:Sprite = _containerMap.getChildByName(pos) as Sprite;
			//areaToReach.addChild(obj);
			_containerMap.addChild(obj);
			obj.x = areaToReach.x+xPos;
			obj.y = areaToReach.y+yPos;
		}
		
		public function destroy():void 
		{
			removeMouseWheelListener();
			removeEventListener(MouseEvent.MOUSE_MOVE, moveToolTip);
			_containerMap.stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
			_containerMap.stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
			if (this.parent != null) parent.removeChild(this);
		}
		
		public function zoomMap(value:int):void 
		{
			trace("[MapBackGround.zoomMap] ", value);
			if (value > 0 && value < 34)
			{
				trace("[MapBackGround.zoomMap] level2");
				TweenLite.to(_containerMap, 1, { transformAroundPoint: { point:new Point(stage.stageWidth/2, stage.stageHeight/2), scale:2 },onStart:removeMouseWheelListener,onComplete:addMouseWheelListener, onUpdate:_blitMask.update, ease:Strong.easeOut } );
			}
			if (value > 34 && value < 66)
			{
				trace("[MapBackGround.zoomMap] level1");
				TweenLite.to(_containerMap, 1, { transformAroundPoint: { point:new Point(stage.stageWidth/2, stage.stageHeight/2), scale:1.5 },onStart:removeMouseWheelListener,onComplete:addMouseWheelListener, onUpdate:_blitMask.update, ease:Strong.easeOut } );
			}
			if (value > 66 && value < 100)
			{
				trace("[MapBackGround.zoomMap] level0");
				TweenLite.to(_containerMap, 1, { transformAroundPoint: { point:new Point(stage.stageWidth/2, stage.stageHeight/2), scale:1 },onStart:removeMouseWheelListener,onComplete:addMouseWheelListener, onUpdate:_blitMask.update, ease:Strong.easeOut } );
			}
		}
		
		
		private function reparentAssets():void 
		{
			_layout =  new Grid(_mapWidth, _mapHeight, 10, 10);
			_bounds = new Rectangle(0, 0, stage.stageWidth, stage.stageHeight);
			_containerMap = new MovieClip();
			this.addChild(_containerMap);
			
			var arr:Array = Gaia.api.getPage(Pages.HOME).assetArray;
			var ln:Number = arr.length;
			for (var i:int = 0; i < ln; i++) 
			{
				if (arr[i] is SpriteAsset)
				{
					var asset:SpriteAsset = SpriteAsset(arr[i]);
					if (StringUtils.contains(asset.id, 'map'))
					{
						IBitmapSprite(asset).smoothing = true;
						asset.visible = true;
						asset.container.name = asset.id;
						_containerMap.addChild(asset.container);
						_layout.addNode(asset.container);
					}
				}
			}
			//addParisMask();
			//addCanal();
			addMarkers();
			addToolTip()
			_blitMask = new BlitMask(_containerMap, _bounds.x, _bounds.y, _bounds.width, _bounds.height, false);
			_blitMask.autoUpdate = true;
			_blitMask.bitmapMode = false;
			_blitMask.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
			//_blitMask.addEventListener(MouseEvent.MOUSE_WHEEL, onMouseWheelEvent);
			moveToArea('map83');
			
		}
		
		private function addToolTip():void 
		{
			_toolTip = new MapToolTip();
			_containerMap.addChild(_toolTip);
			
			TweenMax.to(_toolTip, 0, { autoAlpha:0 } );
		}
		
		private function moveToolTip(e:MouseEvent=null):void 
		{
			if (_toolTip)
			{
				TweenMax.to(_toolTip, .5, { x:_containerMap.mouseX, y:_containerMap.mouseY-20 } );
			}
		}
		
		private function addParisMask():void 
		{
			_parisMask = new ParisMask();
			_parisMask.y = 3192;
			_parisMask.x = -278;
			_containerMap.addChild(_parisMask);
			
		}
		
		private function addCanal():void 
		{
			_canal = new Canal();
			_canal.x = -1;
			_canal.y = -2;
			_containerMap.addChild(_canal);
			
		}
		
		private function addMarkers():void 
		{
			_MarkersArray = [];
			_piXml = Gaia.api.getPage(Pages.TIMELINE).node;
			var ln:int = _piXml.page.length();
			for (var i:int = 0; i < ln; i++) 
			{
				//var obj:Marker = new Marker();
				var obj:MapMarker = new MapMarker();
				obj.name = _piXml.page[i].@id;
				obj.addEventListener(MouseEvent.MOUSE_OVER, _overMarker);
				obj.addEventListener(MouseEvent.MOUSE_OUT, _ouMarker);
				addObjectToArea(obj, _piXml.page[i].@map, _piXml.page[i].@xpos, _piXml.page[i].@ypos);
				//_MarkersArray.push(obj);
			}
		}
		
		private function _ouMarker(e:MouseEvent):void 
		{
			if (_toolTip)
			{
				TweenMax.killTweensOf(_toolTip);
				TweenMax.to(_toolTip, .5, { autoAlpha:0 } );
				removeEventListener(MouseEvent.MOUSE_MOVE, moveToolTip);
			}
			

		}
		
		private function _overMarker(e:MouseEvent):void 
		{
			if (_toolTip)
			{
				_toolTip.over(e);
				moveToolTip();
				TweenMax.to(_toolTip, .5, { autoAlpha:1,delay:.3 } );
				addEventListener(MouseEvent.MOUSE_MOVE, moveToolTip);
			}
			
		}

		private function onMouseWheelEvent(e:MouseEvent):void 
		{
			
			if (!TweenMax.isTweening(_containerMap))
			{
				//_canal.resize();
				_blitMask.update();
				var delta:Number = e.delta;
				if (delta > 0 )
				{
					//_canal.stopEffect();
					//trace("[Main.onMouseWheelEvent] UP");
					if (_containerMap.scaleX < 2)
					{
						TweenLite.to(_containerMap, 1, { transformAroundPoint: { point:new Point(mouseX, mouseY), scale:_containerMap.scaleX + _gap },onStart:removeMouseWheelListener,onComplete:addMouseWheelListener, onUpdate:_blitMask.update, ease:Strong.easeOut } );
					}
				}else
				{
					//_canal.stopEffect();
					//trace("[Main.onMouseWheelEvent] DOWN");
					if (_containerMap.scaleX>1)
					{
						TweenLite.to(_containerMap, 1, {transformAroundPoint:{point:new Point(mouseX,mouseY), scale:_containerMap.scaleX-_gap},onStart:removeMouseWheelListener,onComplete:addMouseWheelListener,onUpdate:_blitMask.update, ease:Strong.easeOut});
					}
				}
				
			}
		}
		
		private function removeMouseWheelListener():void 
		{
			//trace("[MapBackGround.removeMouseWheelListener] ",_containerMap.scaleX);
			_blitMask.removeEventListener(MouseEvent.MOUSE_WHEEL, onMouseWheelEvent);
			_blitMask.removeEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
		}
		
		private function addMouseWheelListener():void 
		{
			//trace("[MapBackGround.addMouseWheelListener] ",_containerMap.scaleX);
			//_blitMask.addEventListener(MouseEvent.MOUSE_WHEEL, onMouseWheelEvent);
			_blitMask.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
				var ln:Number = _MarkersArray.length;
				for (var i:int = 0; i < ln; i++) 
				{
					var item:Marker = _MarkersArray[i] as Marker;
					item.resize();
				}
				//_canal.resize();
				resize()

		}
		
		private function mouseDownHandler(event:MouseEvent=null):void
		{
			TweenLite.killTweensOf(_containerMap);
			x1 = x2 = _containerMap.x;
			xOffset = this.mouseX - _containerMap.x;
			xOverlap = Math.max(0, _containerMap.width - (_bounds.width+71));
			y1 = y2 = _containerMap.y;
			yOffset = this.mouseY - _containerMap.y;
			yOverlap = Math.max(0, _containerMap.height - _bounds.height);
			t1 = t2 = getTimer();
			_containerMap.stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
			_containerMap.stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
		}
		
		private function mouseMoveHandler(event:MouseEvent):void
		{
			var y:Number = this.mouseY - yOffset;
			//if _containerMap's position exceeds the bounds, make it drag only half as far with each mouse movement (like iPhone/iPad behavior)
			if (y > _bounds.top) {
				_containerMap.y = (y + _bounds.top) * 0.5;
			} else if (y < _bounds.top - yOverlap) {
				_containerMap.y = (y + _bounds.top - yOverlap) * 0.5;
			} else {
				_containerMap.y = y;
			}
			var x:Number = this.mouseX - xOffset;
			if (x > _bounds.left) {
				_containerMap.x = (x + _bounds.left) * 0.5;
			} else if (x < _bounds.left - xOverlap) {
				_containerMap.x = (x + _bounds.left - xOverlap) * 0.5;
			} else {
				_containerMap.x = x;
			}
			_blitMask.update();
			var t:uint = getTimer();
			//if the frame rate is too high, we won't be able to track the velocity as well, so only update the values 20 times per second
			if (t - t2 > 50) {
				x2 = x1;
				x1 = _containerMap.x;
				y2 = y1;
				t2 = t1;
				y1 = _containerMap.y;
				t1 = t;
			}
			//if (_canal)_canal.resize();
			event.updateAfterEvent();
		}

		private	function mouseUpHandler(event:MouseEvent):void
		{
			_containerMap.stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
			_containerMap.stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
			var time:Number = (getTimer() - t2) / 1000;
			var xVelocity:Number = (_containerMap.x - x2) / time;
			var yVelocity:Number = (_containerMap.y - y2) / time;
			ThrowPropsPlugin.to(_containerMap, {
				throwProps:{
					y:{velocity:yVelocity, max:_bounds.top, min:_bounds.top - yOverlap, resistance:300},
					x:{velocity:xVelocity, max:_bounds.left, min:_bounds.left - xOverlap, resistance:300}
					},
					//onStart:_blitMask.enableBitmapMode,
					roundProps:["x","y"],
					onUpdate:function():void { _blitMask.update(); /*_canal.resize();*/ },
					ease:Strong.easeOut,
					onComplete:_blitMask.disableBitmapMode
				},
				5,
				1,
				1
			);
		}

			
		private function build(e:Event):void 
		{
			removeEventListener(Event.ADDED_TO_STAGE, build);
			_mapWidth = Number(Gaia.api.getPage(Pages.INDEX).assets.mapPictures.xml.@width);
			_mapHeight = Number(Gaia.api.getPage(Pages.INDEX).assets.mapPictures.xml.@height);
			Model.instance.mapBackground = this;
			reparentAssets();
		}
		
	}

}